iT邦幫忙

2024 iThome 鐵人賽

DAY 4
0

cover

前言

在前幾篇中,我們介紹了 TypeScript 的基本型別與物件型別。在本篇中,將深入探討進階的型別系統,包括聯合型別、交集型別、型別斷言等。

聯合型別 (Union Types)

聯合型別 | ,允許一個值是多種型別之一。這讓我們可以靈活地接受不同的型別輸入,而不用強制規範為單一型別。

// 利用 | 將不同型別聯合在一起,允許 id 是數字或字串
let id: number | string;
id = 123;
id = 'abc123';
// id = false; // Error: 類型 'boolean' 不可指派給類型 'string | number'。

function printId(id: number | string) {
    // 用判斷的方式來推斷型別
    if (typeof id === 'string') {
        // TypeScript 推斷 id 是 string 型別
        console.log(id.toUpperCase());
    } else {
        // TypeScript 推斷 id 是 number 型別
        console.log(id);
    }
}

printId(123); // 123
printId('abc123'); // ABC123

交集型別 (Intersection Types)

交集型別 & ,允許將多種型別合併,從而要求值同時符合多個型別。這在需要融合不同物件的屬性時非常有用。

type Person = {
    name: string;
}

interface Employee {
  position: string;
}

// 利用 & 將不同物件融合,同時會有 Person 與 Employee 的屬性
type EmployeePerson = Person & Employee;

const employee: EmployeePerson = {
    name: 'Johnson Mao',
    position: 'Frontend',
};

console.log(employee.name); // Johnson Mao
console.log(employee.position); // Frontend

注意:
當兩個都是原始類型(例如:string & number)進行交集操作時,結果會是 never 類型,表示沒有任何值能同時是這兩個原始類型。這一點需要特別注意,因為它會導致變數無法賦值任何值。

型別斷言 (type assertion)

型別斷言允許開發者手動告訴 TypeScript 某個值的具體型別。這在 TypeScript 無法正確推斷型別時特別有用,但需小心使用以避免出錯。

// TypeScript 會推斷 inputElement 的類型是 HTMLElement | null
// 我們知道它實際上是 HTMLInputElement,所以需要型別斷言
const inputElement1 = document.getElementById("username") as HTMLInputElement;
inputElement1.value = "New Username";

// 另一種寫法,使用尖括號型別斷言(僅在 .tsx 以外的檔案中可用)
const inputElement2 = <HTMLInputElement>document.getElementById("username");
inputElement2.value = "Another Username";

備註:HTMLInputElement 是 DOM 的類別

可選操作符 (optional operator)

可選操作符 ? 用來表示一個屬性或參數是可選的,即這個屬性或參數可以存在,也可以不傳遞。這為處理物件屬性或函式參數提供了更大的靈活性。

// 物件的可選屬性
interface Person {
    name: string;
    age?: number; // 可選屬性,不一定要有這個屬性
}

const person2: Person = { name: "Mao", age: 18 };
const person1: Person = { name: "Lily" };

// 函式的可選參數,不一定要傳這個參數
function calculateDiscountedPrice(price: number, discount?: number): number {
    let finalPrice = price;

    if (discount) {
        finalPrice -= price * (discount / 100);
    }

    return finalPrice;
}

索引型別(Indexable Type)

允許你定義可以用索引存取的物件型別。這意味著你可以使用索引(通常是字串或數字)來存取物件的屬性,並且可以為這些屬性指定特定的型別。這對於需要動態存取或編寫動態屬性的物件非常有用。

interface StringIndexable {
    [key: string]: number;  // 索引簽名,字串索引對應數字型別
}

const scores: StringIndexable = {
    math: 95,
    english: 88,
    science: 92
};

console.log(scores.math); // 95

此外 PropertyKey 是常規物件可以使用的索引型別,他同時聯集了 string | number | symbol

非空斷言操作符 non-null assertion operator

非空斷言操作符 ! 用來告訴 TypeScript 編譯器,某個值不會是 null 或 undefined,即使編譯器推斷它可能是。這個操作符允許我們在不進行明確檢查的情況下,繼續操作這個值。

// TypeScript 認為 element 可能是 `HTMLElement | null`
const element = document.getElementById("myElement");

// 非空斷言操作符告訴編譯器,element 不會是 `null`
element!.className = "active";

// 但更好的做法會是用判斷的方式推斷
if (element) element.className = "active";

參考文獻


上一篇
TypeScript 基礎:物件、陣列與函式型別
下一篇
TypeScript 基礎:物件導向與類別基礎
系列文
TypeScript 完全指南:從語法基礎到高級功能的系統學習30
圖片
  直播研討會
圖片
{{ item.channelVendor }} {{ item.webinarstarted }} |
{{ formatDate(item.duration) }}
直播中

尚未有邦友留言

立即登入留言